#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "MyString.h"
#include "DynamicArray.h"
#include "StdFile.h"
#include "DoubleLinkList.h"
#include "LoginSignup.h"
// PROCESS
#include <unistd.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/wait.h>

// FIFO
#include <sys/stat.h>
#include <fcntl.h>
// 进程通信MessageQueue
#include <sys/ipc.h>
#include <sys/msg.h>

#define Map_Size 10
#define true 1
#define false 0

struct Player
{
    int HP;
    int attack;
    int x;
    int y;
};
// struct Bag
// {
//     int redkey;
//     int yellowkey;
//     int bluekey;
//     int gold1;
//     int gold2;
//     int gold3;
// };
struct Monster
{
    MyString name;
    int HP;
    int attack;
    int x;
    int y;
};
struct Treasure
{
    MyString name;
    int value;
    int x;
    int y;
};
struct Bag
{
    int treasure;
    int pearl;
    int medicine;
};
// struct User
// {
//     char username[20];
//     char password[20];
// };
// static DLlist UserList;

struct User *CreateUser(const char *username, const char *password)
{
    struct User *user = (struct User *)malloc(sizeof(struct User));

    strcpy(user->name, username);
    strcpy(user->password, password);
    return user;
}
void InitPlayer(struct Player *player)
{
    player->HP = 99999;
    player->attack = 99999;
    player->x = 0;
    player->y = 0;
}
void InitBag(struct Bag *bag)
{
    bag->treasure = 0;
    bag->pearl = 0;
    bag->medicine = 0;
}

int GetRandNUmber(int max)
{
    return rand() % max;
}
struct Bag *CreateBag(int num)
{
    struct Bag *bag = (struct Bag *)malloc(sizeof(struct Bag));
    if (bag == NULL)
    {
        printf("create Bag Error!\n");
        return NULL;
    }
    bag->treasure = num;
    bag->pearl = num;
    bag->medicine = num;
    return bag;
}
struct Monster *CreateMonster(const char *name, int HP, int attack)
{
    struct Monster *monster = (struct Monster *)malloc(sizeof(struct Monster));
    if (monster == NULL)
    {
        printf("create Monster Error!\n");
        return NULL;
    }
    monster->HP = HP;
    monster->attack = attack;
    Initialize(&monster->name, name);
    monster->x = GetRandNUmber(Map_Size);
    monster->y = GetRandNUmber(Map_Size);
    return monster;
}
struct Treasure *CreateTreasure(const char *name, int value)
{
    struct Treasure *treasure = (struct Treasure *)malloc(sizeof(struct Treasure));
    if (treasure == NULL)
    {
        printf("create treasure Error!\n");
        return NULL;
    }

    Initialize(&treasure->name, name);
    treasure->value = value;

    treasure->x = GetRandNUmber(Map_Size);
    treasure->y = GetRandNUmber(Map_Size);
    return treasure;
}
struct Monster *CreatePrevMonster(const char *name, int HP, int attack, int x, int y)
{
    struct Monster *monster = (struct Monster *)malloc(sizeof(struct Monster));
    if (monster == NULL)
    {
        printf("Create Monster Error!\n");
        return NULL;
    }

    monster->attack = attack;
    monster->HP = HP;
    Initialize(&monster->name, name);

    monster->x = x;
    monster->y = y;

    return monster;
}

struct Treasure *CreatePrevTreasure(const char *name, int value, int x, int y)
{
    struct Treasure *Treasure = (struct Treasure *)malloc(sizeof(struct Treasure));
    if (Treasure == NULL)
    {
        printf("Create Treasure Error!\n");
        return NULL;
    }

    Initialize(&Treasure->name, name);

    Treasure->value = value;
    Treasure->x = x;
    Treasure->y = y;

    return Treasure;
}
void InitMonsters(struct DynamicArray *array)
{
    if (ArrayInit(array) == false)
    {
        return;
    }
    InsertArray(array, CreateMonster("山岭巨人", 100, 20));
    InsertArray(array, CreateMonster("鲍勃", 50, 10));
    InsertArray(array, CreateMonster("jo太郎", 50, 10));
    InsertArray(array, CreateMonster("PIG", 50, 10));
    InsertArray(array, CreateMonster("MOUSE", 20, 5));
    InsertArray(array, CreateMonster("MOUSE", 20, 5));
    InsertArray(array, CreateMonster("MOUSE", 20, 5));
    InsertArray(array, CreateMonster("MOUSE", 20, 5));
    InsertArray(array, CreateMonster("MOUSE", 20, 5));
}

void InitTreasures(struct DynamicArray *array)
{
    if (ArrayInit(array) == false)
    {
        return;
    }
    InsertArray(array, CreateTreasure("treasure", 100));
    InsertArray(array, CreateTreasure("pearl", 50));
    InsertArray(array, CreateTreasure("pearl", 50));
    InsertArray(array, CreateTreasure("pearl", 50));
    InsertArray(array, CreateTreasure("medicine", 20));
    InsertArray(array, CreateTreasure("medicine", 20));
    InsertArray(array, CreateTreasure("medicine", 20));
    InsertArray(array, CreateTreasure("medicine", 20));
    InsertArray(array, CreateTreasure("medicine", 20));
}
void InitPrevTresure(struct DynamicArray *Treasures)
{
    if (ArrayInit(Treasures) == false)
    {
        return;
    }

    DLlist *treasure = GetLineFromFile("Treasure.txt");
    struct Node *travelpoint = treasure->head;

    while (travelpoint != NULL)
    {
        char *temp = (char *)travelpoint->data;
        char treasure_name[100];
        int treasure_value = 0;
        int treasure_x = 0;
        int treasure_y = 0;
        strcpy(treasure_name, strtok(temp, " "));
        treasure_value = atoi(strtok(NULL, " "));
        treasure_x = atoi(strtok(NULL, " "));
        treasure_y = atoi(strtok(NULL, " "));
        InsertArray(Treasures, CreatePrevTreasure(treasure_name, treasure_value, treasure_x, treasure_y));
        // printf("%s %d %d\n",treasure_name,treasure_x,treasure_y);
        travelpoint = travelpoint->next;
    }
}

void InitPrevMonster(struct DynamicArray *monsters)
{
    if (ArrayInit(monsters) == false)
    {
        return;
    }

    DLlist *monsterlist = GetLineFromFile("monster.txt");
    struct Node *travelpoint = monsterlist->head;

    while (travelpoint != NULL)
    {
        char *temp = (char *)travelpoint->data;
        char monster_name[100];
        int monster_HP = 0;
        int monster_attack = 0;
        int monster_x = 0;
        int monster_y = 0;
        strcpy(monster_name, strtok(temp, " "));
        monster_HP = atoi(strtok(NULL, " "));
        monster_attack = atoi(strtok(NULL, " "));
        monster_x = atoi(strtok(NULL, " "));
        monster_y = atoi(strtok(NULL, " "));
        InsertArray(monsters, CreatePrevMonster(monster_name, monster_HP, monster_attack, monster_x, monster_y));
        // printf("%s %d %d\n",monster_name,monster_x,monster_y);
        travelpoint = travelpoint->next;
    }
}

void StoreMonsters(struct DynamicArray *Monster, char *account)
{
    char a[100] = {0};
    strcpy(a, account);
    strcat(a, "monster.txt");
    FILE *file = fopen(a, "w+"); // 存用户注册信息
    if (file == NULL)
    {
        printf("file open fail!\n");
    }

    for (int i = 0; i < Monster->len; i++)
    {
        struct Monster *monster = (struct Monster *)Monster->dp[i];
        fprintf(file, "%s %d %d %d %d\n", monster->name.string, monster->HP, monster->attack, monster->x, monster->y);
    }
}
void StorePlayer(struct Player *player, char *account)
{
    // printf("%s", account);
    char a[100] = {0};
    strcpy(a, account);
    strcat(a, ".txt");
    FILE *file = fopen(a, "w+"); // 存用户注册信息
    if (file == NULL)
    {
        printf("file open fail!\n");
    }
    fprintf(file, "%d %d %d %d \n", player->HP, player->attack, player->x, player->y);
}

void StoreTreasure(struct DynamicArray *Treasures, char *account)
{
    char a[100] = {0};
    strcpy(a, account);
    strcat(a, "treasure.txt");
    FILE *file = fopen(a, "w+"); // 存用户注册信息
    if (file == NULL)
    {
        printf("file open fail!\n");
    }

    for (int i = 0; i < Treasures->len; i++)
    {
        struct Treasure *treasure = (struct Treasure *)Treasures->dp[i];
        fprintf(file, "%s %d %d %d\n", treasure->name.string, treasure->value, treasure->x, treasure->y);
    }
}

int checkBag(struct Bag *Bag)
{
    printf("您拥有宝藏：%d 珍珠： %d 药水 %d\n", Bag->treasure, Bag->pearl, Bag->medicine);
}

void MakeMove(struct Player *player, struct DynamicArray *Monster, struct DynamicArray *treasure, struct Bag *Bag, char symbol, char *account)
{
    switch (symbol)
    {
    case 'w':
        player->y--;
        break;
    case 'W':
        player->y--;
        break;
    case 's':
        player->y++;
        break;
    case 'S':
        player->y++;
        break;
    case 'a':
        player->x--;
        break;
    case 'A':
        player->x--;
        break;
    case 'd':
        player->x++;
        break;
    case 'D':
        player->x++;
        break;
    case '1':
        StoreMonsters(Monster, account);
        StorePlayer(player, account);
        StoreTreasure(treasure, account);
        exit(1);
        break;
    case 'b':
        checkBag(Bag);
        break;
    case 'B':
        checkBag(Bag);
        break;
    default:
        break;
    }

    if (player->x < 0)
        player->x = 0;
    if (player->x >= Map_Size)
        player->x = Map_Size - 1;
    if (player->y < 0)
        player->y = 0;
    if (player->y >= Map_Size)
        player->y = Map_Size - 1;
}

int check(int num, struct Monster *monster)
{
    int i;
    if (num >= 1 && num <= 4)
        return num;
    else
    {
        system("clear\n");
        printf("    ==============战斗报告=============\n");
        printf("    您遭遇了|%s|血量:|%d|  攻击力:|%d|\n", monster->name.string, monster->HP, monster->attack);
        printf("****************************************\n");
        printf("*                 fight                *\n");
        printf("****************************************\n");
        printf("请选择!\n");
        printf("1,普通攻击\n");
        printf("2,认真一拳\n");
        printf("3,尝试逃跑\n");
        printf("4,坚固铠甲(抵消并反弹伤害给怪物)\n");

        scanf("%d", &i);
        while (getchar() != '\n')
            ;
        return check(i, monster);
    }
}
int GetStuff(struct Treasure *Treasure, struct Bag *Bag)
{
    if (strcmp(Treasure->name.string, "treasure") == 0)
        Bag->treasure = Bag->treasure + 1;
    if (strcmp(Treasure->name.string, "pearl") == 0)
        Bag->pearl = Bag->pearl + 1;
    if (strcmp(Treasure->name.string, "medicine") == 0)
        Bag->medicine = Bag->medicine + 1;
}
int Battle(struct Player *player, struct Monster *monster, struct Treasure *Treasure)
{

    // system("clear\n");
    printf("==============战斗报告=============\n");
    printf("您遭遇了|%s|血量:|%d|  攻击力:|%d|\n", monster->name.string, monster->HP, monster->attack);
    printf("****************************************\n");
    printf("*                  战斗                *\n");
    printf("****************************************\n");
    while (player->HP > 0 && monster->HP > 0)
    {
        printf("请选择!\n");
        printf("1,普通攻击\n");
        printf("2,认真一拳\n");
        printf("3,尝试逃跑\n");
        printf("4,坚固铠甲(抵消并反弹伤害给怪物)\n");
        int num;
        scanf("%d", &num);
        while (getchar() != '\n')
            ;

        num = check(num, monster);
        // a = check(a);

        switch (num)
        {
        case 1:
            player->HP -= monster->attack;
            monster->HP -= player->attack;
            printf("|%s| 对你造成了%d的伤害  你的生命为%d |%s|的生命为%d\n", monster->name.string, monster->attack, player->HP, monster->name.string, monster->HP);
            printf("你 对|%s|造成了%d的伤害  你的生命为%d |%s|的生命为%d\n", monster->name.string, player->attack, player->HP, monster->name.string, monster->HP);
            sleep(1.5);
            break;
        case 2:
            if (GetRandNUmber(2) == 1)
            {
                player->HP -= monster->attack;
                monster->HP -= player->attack * 2;
                printf("|%s| 对你造成了%d的伤害  你的生命为%d |%s|的生命为%d\n", monster->name.string, monster->attack, player->HP, monster->name.string, monster->HP);
                printf("你 对|%s|造成了%d的伤害  你的生命为%d |%s|的生命为%d\n", monster->name.string, player->attack * 2, player->HP, monster->name.string, monster->HP);
                sleep(1.5);
            }
            else
            {
                printf("|%s| 对你造成了%d的伤害  你的生命为%d |%s|的生命为%d\n", monster->name.string, monster->attack, player->HP, monster->name.string, monster->HP);
                printf("暴击失败！无法发动攻击\n");
                player->HP -= monster->attack;
                sleep(1.5);
            }
            break;
        case 3:

            if (GetRandNUmber(2) == 1)
            {

                player->x += 1;
                player->y += 1;
                printf("逃跑成功!\n");
                sleep(1.5);
                return true;
            }
            else
            {
                printf("逃跑失败!\n");
                printf("|%s| 对你造成了%d的伤害  你的生命为%d |%s|的生命为%d\n", monster->name.string, monster->attack, player->HP, monster->name.string, monster->HP);
                player->HP -= monster->attack;
                sleep(1.5);
                system("clear\n");
                printf("您激怒了|%s|血量:|%d|  攻击力:|%d|\n", monster->name.string, monster->HP, monster->attack * 2);
                printf("****************************************\n");
                printf("*                 fight                *\n");
                printf("****************************************\n");
            }
            break;
        case 4:
        {
            monster->HP -= monster->attack;
            printf("你 对|%s|造成了%d的伤害  你的生命为%d |%s|的生命为%d\n", monster->name.string, monster->attack, player->HP, monster->name.string, monster->HP);
            sleep(1.5);
        }
        break;
        }
        printf("======================end======================\n");
        if (player->HP <= 0)
        {
            printf("你被|%s|击败了!\n", monster->name.string);
            player->HP = 0;
            sleep(1.5);
            return false;
        }
        if (monster->HP <= 0)
        {
            printf("你击败了|%s|!\n", monster->name.string);
            sleep(1.5);
            system("clear\n");
            return true;
        }
    }
}
void Initboard(char (*p)[Map_Size])
{
    for (int i = 0; i < Map_Size; i++)
    {
        for (int j = 0; j < Map_Size; j++)
        {
            p[i][j] = '-';
        }
    }
}
void PrintMap(char (*p)[Map_Size], struct Player *player)
{
    // system("clear\n");
    printf("************************************************\n");
    printf("*                   魔塔冒险                   *\n");
    printf("************************************************\n");
    Initboard(p);
    p[player->x][player->y] = 'Q';
    printf("\n");
    printf("     ");
    for (int i = 0; i < Map_Size; i++)
    {
        printf(" %3d", i + 1);
    }
    printf("\n");
    for (int i = 0; i < Map_Size; i++)
    {
        printf(" %4d", i + 1);
        for (int j = 0; j < Map_Size; j++)
        {
            printf("%4c", p[j][i]);
        }
        printf("\n");
    }
}

int main()
{
    DLlist GameUserData;
    InitDLlist(&GameUserData);

    // DLlist *list = GetLineFromFile("UserInformation.txt"); // 读文件
    // Trave(list, StrTok, GameUserData);

    srand(time(NULL));

    char board[Map_Size][Map_Size];
    Initboard(board);

    struct Player player;
    // InitPlayer(&player);

    struct DynamicArray monsters = {NULL, 10, 0};
    // InitMonsters(&monsters);

    struct DynamicArray treasures = {NULL, 10, 0};
    // InitTreasures(&treasures);
    struct Bag Bag;

    srand(time(NULL)); // 使每时每刻的随机值都不一样
    system("clear");
    // char account[100];
    // account = start(&GameUserData);
    // char account[100] = start(&GameUserData);
    char *account = (char *)malloc(sizeof(char) * 100);
    account = start(&GameUserData);

    start2();

    int i;
    scanf("%d", &i);

    while (i != 1 & i != 2)
    {
        printf("请再次输入:\n");
        scanf("%d\n", &i);
    }
    switch (i)
    {
    case 1:

        char a[100] = {0};
        strcpy(a, account);
        strcat(a, ".txt");
        FILE *file = fopen(a, "a+");

        if (file == NULL)
        {
            printf("没有旧的存档!\n");
            exit(1);
        }

        char ContentTemp[100] = {0};
        fgets(ContentTemp, 100, fopen(a, "a+"));
        char *Line = (char *)malloc(strlen(ContentTemp) + 1);
        strcpy(Line, ContentTemp);

        player.HP = (atoi)(strtok(Line, " "));
        player.attack = (atoi)(strtok(NULL, " "));
        player.x = (atoi)(strtok(NULL, " "));
        player.y = (atoi)(strtok(NULL, " "));
        // printf("%d %d\n", player.x, player.y);

        InitPrevTresure(&treasures);
        InitPrevMonster(&monsters);
        InitBag(&Bag);
        break;

    case 2:
        InitMonsters(&monsters);
        InitTreasures(&treasures);
        InitPlayer(&player);
        InitBag(&Bag);
        break;
    }

    while (1)
    {

        for (int i = 0; i < monsters.len; i++)
        {
            struct Monster *monster = (struct Monster *)monsters.dp[i];
            struct Treasure *treasure = (struct Treasure *)treasures.dp[i];
            struct Bag *Bag = (struct Bag *)Bag;
            if (monster->HP > 0 && monster->x == player.x && monster->y == player.y)
            {
                if (Battle(&player, monster, treasure) == false)
                {
                    printf("游戏结束!\n");
                    break;
                }
                if (Battle(&player, monster, treasure) == true)
                {
                    // 升级
                }
            }
            if (treasure->x == player.x && treasure->y == player.y) // 背包
            {
                GetStuff(treasure, Bag);
                printf("捡到了宝物快打开背包查看吧！\n");
            }
            if (player.HP == 0)
                break;
        }
        // system("clear");
        PrintMap(board, &player);
        printf("您当前所在的位置是<%d,%d>\n", player.x + 1, player.y + 1);
        printf("请在键盘选择你要进行操作:\n移动('w','s','a','d')\n查看背包('b')\n输入1保存游戏信息并退出\n");
        printf("\n");
        char choice;
        scanf("%c", &choice);
        MakeMove(&player, &monsters, &treasures, &Bag, choice, account);
        // system("clear");
    }
    for (int i = 0; i < monsters.len; i++)
    {
        struct Monster *monster = (struct Monster *)monsters.dp[i];
        free(monster->name.string);
        free(monster);
    }
    free(monsters.dp);

    return 0;
}